﻿namespace CatchBall
{
    using System;
    using System.Diagnostics;
    using System.IO;
    using System.Threading;

    public class Game
    {
        public const int FieldXDimension = 60;

        public const int FieldYDimension = 20;

        private Stopwatch timePlayed = new Stopwatch();

        private static int chosenGunSpeed;

        private static int chosenBallSpeed;

        private Random randomGenerator = new Random();

        // initializer with default values for time and score
        public Game()
        {
            this.Open();
            this.Score = 0;
            this.Time = 0.10f;
        }

        public string ChosenLevel { get; set; }

        // Score and Time for the game
        public int Score { get; set; }

        private float Time { get; set; }

        // must be used after GameOver()
        public TimeSpan CalculatingPlayedTimeFromAllPlayingSessions()
        {
            StreamReader input = new StreamReader(@"..\..\External Files\AllTimePlayed.txt");
            string time = null;
            using (input)
            {
                time = input.ReadLine();
            }

            string[] allTime = time.Split('.', ':');
            string currentTime = this.timePlayed.Elapsed.ToString();
            string[] currentTimePlayed = currentTime.Split('.', ':');
            TimeSpan allTimeSpan = new TimeSpan(hours: int.Parse(allTime[0]), minutes: int.Parse(allTime[1]), seconds: int.Parse(allTime[2]));
            TimeSpan currentTimePlayedSpan = new TimeSpan(hours: int.Parse(currentTimePlayed[0]), minutes: int.Parse(currentTimePlayed[1]), seconds: int.Parse(currentTimePlayed[2]));
            TimeSpan newTime = allTimeSpan + currentTimePlayedSpan;
            StreamWriter output = new StreamWriter(@"..\..\External Files\AllTimePlayed.txt");
            using (output)
            {
                output.WriteLine(newTime);
            }

            return newTime;
        }

        public void Open()
        {
            Console.ForegroundColor = ConsoleColor.Green;
            var catchballtext = new string[6];
            catchballtext[0] = " ____  ____ _____ ____ _   _               ";
            catchballtext[1] = "/ (__`/ () |_   _/ (__| |_| |              ";
            catchballtext[2] = "\\____/__/\\__\\|_| \\____|_| |_|              ";
            catchballtext[3] = "                  _____  ____  _    _      ";
            catchballtext[4] = "                  | () )/ () \\| |__| |__   ";
            catchballtext[5] = "                  |_()_/__/\\__|____|____|  ";

            var length = Console.WindowWidth - 2;
            var heighStart = (Console.WindowHeight / 2) - 3;
            var finalStartPosition = length - ((length - catchballtext[0].Length) / 2);
            MainCatchBall.PlayAudioFile("../../External Files/music.wav", true);

            for (var i = 0; i < finalStartPosition; i++)
            {
                for (var j = 0; j < 6; j++)
                {
                    Console.SetCursorPosition(Console.WindowWidth - i - 1, heighStart + j);

                    for (var k = 0; k < Math.Min(i, catchballtext[j].Length); k++)
                    {
                        Console.Write(catchballtext[j][k]);
                    }
                }

                Thread.Sleep(5);
            }

            Console.ResetColor();
            Console.SetCursorPosition((Console.WindowWidth / 2) - 10, Console.WindowHeight - 3);
            Console.WriteLine("PRESS ANY KEY TO START");
            Console.ReadKey();
            Console.Clear();
            this.ChosenLevel = ChooseLevel();
            chosenGunSpeed = this.SetGunSpeed();
            chosenBallSpeed = this.SetBallSpeed();
        }

        public void Play(Scores scores)
        {
            // make all objects in the game and visualize them
            Console.CursorVisible = false;
            CreateField();
            var player = new Player();
            player.VisualizePlayer();
            var ball = new Ball();
            ball.VisualizeBall();
            var gun = new Gun();
            gun.VisualizeWeapon();
            this.VisualizeScore();
            this.VisualizeTime();

            this.timePlayed.Start();

            var timer = 0;
            var speed = 0;
            // int prevWepRow = 2; // TODO: remove from the code, eventually
            var isShot = false;
            while (this.Time > 0.01)
            {
                if (Console.KeyAvailable)
                {
                    player.ListenKey(ball, this);
                }

                if (speed % chosenGunSpeed == 0)
                {
                    isShot = player.Col == (gun.Row + 1); // don't fix player.Col to .Row because player x and y are reversed
                    gun.MoveWeapon();
                    // MoveShot(prevWepRow, rowPlayer); // TODO: remove from the code, eventually
                }

                if (isShot == true)
                {
                    MainCatchBall.PlayAudioFile("../../External Files/gun.wav");
                  
                    break;
                }

                Thread.Sleep(10);

                if (speed % chosenBallSpeed == 0)
                {
                    ball.MoveBall();
                }

                speed++;

                if (timer % 100 == 0)
                {
                    this.Time -= 0.01f;
                    this.VisualizeTime();
                }

                timer++;
            }

            Console.Clear();
            this.GameOver(isShot, scores);
        }

        // prints the score
        public void VisualizeScore()
        {
            Console.SetCursorPosition(10, 22);
            Console.Write("Score: {0}", this.Score);

            MainCatchBall.PlayAudioFile("../../External Files/point.wav");
        }

        // draws the field at the beginning of the game
        private static void CreateField()
        {
            for (var i = 1; i < 20; i += 2)
            {
                for (var j = 1; j < 60; j += 2)
                {
                    Console.SetCursorPosition(j, i);
                    Console.Write('■');
                }

                Console.WriteLine();
            }
        }

        // difficulty
        private static string ChooseLevel()
        {
            Console.SetCursorPosition(25, 7);
            Console.ForegroundColor = ConsoleColor.Green;
            Console.Write("Choose Level 1-5: ");
            string pressedKey;
            do
            {
                Console.CursorVisible = true;
                pressedKey = Console.ReadLine();
                Console.CursorVisible = false;
                Console.SetCursorPosition(44, 7);
                Console.Write("\b"); // TODO: it is not working at my PC
            }
            while ((pressedKey != "1") && (pressedKey != "2") && (pressedKey != "3") && (pressedKey != "4") && (pressedKey != "5"));
            Console.ResetColor();
            Console.SetCursorPosition(45, 7);
            Console.Write("\b");
            Console.Write("\b");
            Console.Clear();
            return pressedKey;
        }

        private int SetGunSpeed()
        {
            if (this.ChosenLevel == "1")
            {
                return 250;
            }
            else if (this.ChosenLevel == "2")
            {
                return 190;
            }
            else if (this.ChosenLevel == "3")
            {
                return 150;
            }
            else if (this.ChosenLevel == "4")
            {
                return 120;
            }
            else
            {
                return 100;
            }
        }

        private int SetBallSpeed()
        {
            if (this.ChosenLevel == "1")
            {
                return 180;
            }
            else if (this.ChosenLevel == "2")
            {
                return 140;
            }
            else if (this.ChosenLevel == "3")
            {
                return 100;
            }
            else if (this.ChosenLevel == "4")
            {
                return 70;
            }
            else
            {
                return 50;
            }
        }

        // prints the time
        private void VisualizeTime()
        {
            Console.SetCursorPosition(22, 22);
            Console.Write("Time: {0:f2}", this.Time);
        }

        private bool MoveShot(int row, int rowPlayer)
        {
            var endGame = false;
            row++;
            Console.ForegroundColor = ConsoleColor.Yellow;
            for (var col = 59; col >= 1; col -= 2)
            {
                Console.SetCursorPosition(col, row);
                Console.Write('■');
            }

            if (row == rowPlayer)
            {
                endGame = true;
            }

            Console.ResetColor();
            for (var col = 59; col >= 1; col -= 2)
            {
                Console.SetCursorPosition(col, row);
                Console.Write('■');

                // Thread.Sleep(1);
            }

            return endGame;
        }

        // display your score after the game ended
        private void GameOver(bool endGame, Scores scores)
        {
            this.timePlayed.Stop();
            TimeSpan justDeclaringVar = CalculatingPlayedTimeFromAllPlayingSessions();

            if (endGame)
            {
                Console.SetCursorPosition(21, 9);
                Console.Write("You have been shot!");
            }

            Console.SetCursorPosition(25, 5);
            Console.ForegroundColor = ConsoleColor.Red;
            Console.Write("Game over");
            Console.ResetColor();
            Console.SetCursorPosition(25, 7);
            Console.Write("Your score: {0}", this.Score);
            Console.SetCursorPosition(23, 13);
            scores.VictoryCeremony(this.Score);
            Console.SetCursorPosition(23, 13);

            for (var i = 0; i < 10; i++)
            {
                Thread.Sleep(100);
            }

            MainCatchBall.PlayAudioFile("../../External Files/end.wav");
        }
    }
}